{
  "cells": [
    {
      "cell_type": "markdown",
      "metadata": {
        "id": "PdKwzEluDBN7"
      },
      "source": [
        "# Install openai-agents SDK"
      ]
    },
    {
      "cell_type": "code",
      "execution_count": 1,
      "metadata": {
        "colab": {
          "base_uri": "https://localhost:8080/"
        },
        "id": "3QdkOviEB2ay",
        "outputId": "aa4be980-0786-43c2-b6f7-6e20e3be9b28"
      },
      "outputs": [
        {
          "name": "stdout",
          "output_type": "stream",
          "text": [
            "\u001b[?25l   \u001b[90m━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━\u001b[0m \u001b[32m0.0/76.1 kB\u001b[0m \u001b[31m?\u001b[0m eta \u001b[36m-:--:--\u001b[0m\r\u001b[2K   \u001b[90m━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━\u001b[0m \u001b[32m76.1/76.1 kB\u001b[0m \u001b[31m2.3 MB/s\u001b[0m eta \u001b[36m0:00:00\u001b[0m\n",
            "\u001b[2K   \u001b[90m━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━\u001b[0m \u001b[32m128.6/128.6 kB\u001b[0m \u001b[31m6.7 MB/s\u001b[0m eta \u001b[36m0:00:00\u001b[0m\n",
            "\u001b[2K   \u001b[90m━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━\u001b[0m \u001b[32m567.4/567.4 kB\u001b[0m \u001b[31m8.1 MB/s\u001b[0m eta \u001b[36m0:00:00\u001b[0m\n",
            "\u001b[?25h"
          ]
        }
      ],
      "source": [
        "!pip install -Uq openai-agents"
      ]
    },
    {
      "cell_type": "markdown",
      "metadata": {
        "id": "7yD91lz4DIAx"
      },
      "source": [
        "# Make your Notebook capable of running asynchronous functions.\n",
        "Both Jupyter notebooks and Python’s asyncio library utilize event loops, but they serve different purposes and can sometimes interfere with each other.\n",
        "\n",
        "The nest_asyncio library allows the existing event loop to accept nested event loops, enabling asyncio code to run within environments that already have an event loop, such as Jupyter notebooks.\n",
        "\n",
        "In summary, both Jupyter notebooks and Python’s asyncio library utilize event loops to manage asynchronous operations. When working within Jupyter notebooks, it’s essential to be aware of the existing event loop to effectively run asyncio code without conflicts."
      ]
    },
    {
      "cell_type": "code",
      "execution_count": 2,
      "metadata": {
        "id": "C8YXyIpiZ9v4"
      },
      "outputs": [],
      "source": [
        "import nest_asyncio\n",
        "nest_asyncio.apply()"
      ]
    },
    {
      "cell_type": "markdown",
      "metadata": {
        "id": "wQsVowow7ihQ"
      },
      "source": [
        "# Config"
      ]
    },
    {
      "cell_type": "code",
      "execution_count": 3,
      "metadata": {
        "id": "XnusaX_RWF22"
      },
      "outputs": [],
      "source": [
        "from agents import (\n",
        "    AsyncOpenAI,\n",
        "    OpenAIChatCompletionsModel,\n",
        ")\n",
        "from google.colab import userdata\n"
      ]
    },
    {
      "cell_type": "code",
      "execution_count": 5,
      "metadata": {
        "id": "oPvcFwItoKqw"
      },
      "outputs": [],
      "source": [
        "gemini_api_key = userdata.get(\"GEMINI_API_KEY\")\n",
        "\n",
        "\n",
        "# Check if the API key is present; if not, raise an error\n",
        "if not gemini_api_key:\n",
        "    raise ValueError(\"GEMINI_API_KEY is not set. Please ensure it is defined in your .env file.\")\n",
        "\n",
        "#Reference: https://ai.google.dev/gemini-api/docs/openai\n",
        "external_client = AsyncOpenAI(\n",
        "    api_key=gemini_api_key,\n",
        "    base_url=\"https://generativelanguage.googleapis.com/v1beta/openai/\",\n",
        ")\n",
        "\n",
        "model = OpenAIChatCompletionsModel(\n",
        "    model=\"gemini-2.0-flash\",\n",
        "    openai_client=external_client\n",
        ")"
      ]
    },
    {
      "cell_type": "code",
      "execution_count": 6,
      "metadata": {
        "id": "y9LkW-F7nC3T"
      },
      "outputs": [],
      "source": [
        "from agents import set_default_openai_client, set_tracing_disabled\n",
        "set_default_openai_client(external_client)\n",
        "set_tracing_disabled(True)"
      ]
    },
    {
      "cell_type": "markdown",
      "metadata": {
        "id": "rWL7EnI_7mIF"
      },
      "source": [
        "# Learning LifeCycle"
      ]
    },
    {
      "cell_type": "code",
      "execution_count": 8,
      "metadata": {
        "id": "xL1SE0WBzNfB"
      },
      "outputs": [],
      "source": [
        "# Imports\n",
        "import asyncio\n",
        "import random\n",
        "from typing import Any\n",
        "\n",
        "from pydantic import BaseModel\n",
        "\n",
        "from agents import Agent, RunContextWrapper, AgentHooks, Runner, Tool, function_tool"
      ]
    },
    {
      "cell_type": "markdown",
      "metadata": {
        "id": "ZF1dd25XzEBp"
      },
      "source": [
        "### 1. Basic Example (Understand Core Concept)"
      ]
    },
    {
      "cell_type": "code",
      "execution_count": 19,
      "metadata": {
        "id": "gfScTeRmzQYS"
      },
      "outputs": [],
      "source": [
        "class TestAgHooks(AgentHooks):\n",
        "    def __init__(self, ag_display_name):\n",
        "        self.event_counter = 0\n",
        "        self.ag_display_name = ag_display_name\n",
        "\n",
        "    async def on_start(self, context: RunContextWrapper, agent: Agent) -> None:\n",
        "        self.event_counter += 1\n",
        "        print(f\"### {self.ag_display_name} {self.event_counter}: Agent {agent.name} started. Usage: {context.usage}\")\n",
        "\n",
        "    async def on_end(self, context: RunContextWrapper, agent: Agent, output: Any) -> None:\n",
        "        self.event_counter += 1\n",
        "        print(f\"### {self.ag_display_name} {self.event_counter}: Agent {agent.name} ended. Usage: {context.usage}, Output: {output}\")"
      ]
    },
    {
      "cell_type": "code",
      "execution_count": 20,
      "metadata": {
        "colab": {
          "base_uri": "https://localhost:8080/"
        },
        "id": "CzedWWWrzfQD",
        "outputId": "d2d729b5-ecf0-4283-bdf8-cb2cfc5f5f87"
      },
      "outputs": [
        {
          "name": "stdout",
          "output_type": "stream",
          "text": [
            "### content_moderator 1: Agent Content Moderator Agent started. Usage: Usage(requests=0, input_tokens=0, output_tokens=0, total_tokens=0)\n",
            "### content_moderator 2: Agent Content Moderator Agent ended. Usage: Usage(requests=1, input_tokens=47, output_tokens=35, total_tokens=82), Output: This tweet expresses a concern or question about the future of \"Agentic AI.\" Since it's a question about AI, I'll flag it for potential answering.\n",
            "\n",
            "This tweet expresses a concern or question about the future of \"Agentic AI.\" Since it's a question about AI, I'll flag it for potential answering.\n",
            "\n",
            "--end--\n"
          ]
        }
      ],
      "source": [
        "start_agent = Agent(\n",
        "    name=\"Content Moderator Agent\",\n",
        "    instructions=\"You are content moderation agent. Watch social media content received and flag queries that need help or answer. We will answer anything about AI?\",\n",
        "    hooks=TestAgHooks(ag_display_name=\"content_moderator\"),\n",
        "    model=model\n",
        ")\n",
        "\n",
        "async def main():\n",
        "  result = await Runner.run(\n",
        "      start_agent,\n",
        "      input=f\"<tweet>Will Agentic AI Die at end of 2025?.</tweet>\"\n",
        "  )\n",
        "\n",
        "  print(result.final_output)\n",
        "\n",
        "asyncio.run(main())\n",
        "print(\"--end--\")"
      ]
    },
    {
      "cell_type": "markdown",
      "metadata": {
        "id": "pqF1gaVZ2R0l"
      },
      "source": [
        "We can add callbacks on various lifecycle events in an agent run listed here:\n",
        "\n",
        "https://openai.github.io/openai-agents-python/ref/lifecycle/#agents.lifecycle.AgentHooks"
      ]
    },
    {
      "cell_type": "markdown",
      "metadata": {
        "id": "cM8n3d4GzGGz"
      },
      "source": [
        "### 2. Advanced Example (With Tools and Agents HandOff)"
      ]
    },
    {
      "cell_type": "code",
      "execution_count": 10,
      "metadata": {
        "id": "2XzWlsI2yue2"
      },
      "outputs": [],
      "source": [
        "class CustomAgentHooks(AgentHooks):\n",
        "    def __init__(self, display_name: str):\n",
        "        self.event_counter = 0\n",
        "        self.display_name = display_name\n",
        "\n",
        "    async def on_start(self, context: RunContextWrapper, agent: Agent) -> None:\n",
        "        self.event_counter += 1\n",
        "        print(f\"### ({self.display_name}) {self.event_counter}: Agent {agent.name} started\")\n",
        "\n",
        "    async def on_end(self, context: RunContextWrapper, agent: Agent, output: Any) -> None:\n",
        "        self.event_counter += 1\n",
        "        print(\n",
        "            f\"### ({self.display_name}) {self.event_counter}: Agent {agent.name} ended with output {output}\"\n",
        "        )\n",
        "\n",
        "    async def on_handoff(self, context: RunContextWrapper, agent: Agent, source: Agent) -> None:\n",
        "        self.event_counter += 1\n",
        "        print(\n",
        "            f\"### ({self.display_name}) {self.event_counter}: Agent {source.name} handed off to {agent.name}\"\n",
        "        )\n",
        "\n",
        "    async def on_tool_start(self, context: RunContextWrapper, agent: Agent, tool: Tool) -> None:\n",
        "        self.event_counter += 1\n",
        "        print(\n",
        "            f\"### ({self.display_name}) {self.event_counter}: Agent {agent.name} started tool {tool.name}\"\n",
        "        )\n",
        "\n",
        "    async def on_tool_end(\n",
        "        self, context: RunContextWrapper, agent: Agent, tool: Tool, result: str\n",
        "    ) -> None:\n",
        "        self.event_counter += 1\n",
        "        print(\n",
        "            f\"### ({self.display_name}) {self.event_counter}: Agent {agent.name} ended tool {tool.name} with result {result}\"\n",
        "        )"
      ]
    },
    {
      "cell_type": "code",
      "execution_count": 14,
      "metadata": {
        "colab": {
          "base_uri": "https://localhost:8080/"
        },
        "id": "S11ItAh-resv",
        "outputId": "d2939cca-f446-4444-f07f-620b08db4e5d"
      },
      "outputs": [
        {
          "name": "stdout",
          "output_type": "stream",
          "text": [
            "Enter a max number: 3\n",
            "### (Start Agent) 1: Agent Start Agent started\n",
            "### (Start Agent) 2: Agent Start Agent started tool random_number\n",
            "### (Start Agent) 3: Agent Start Agent ended tool random_number with result 3\n",
            "### (Start Agent) 4: Agent Start Agent handed off to Multiply Agent\n",
            "### (Multiply Agent) 1: Agent Multiply Agent started\n",
            "### (Multiply Agent) 2: Agent Multiply Agent started tool multiply_by_two\n",
            "### (Multiply Agent) 3: Agent Multiply Agent ended tool multiply_by_two with result 6\n",
            "### (Multiply Agent) 4: Agent Multiply Agent ended with output The final result is 6.\n",
            "Done!\n"
          ]
        }
      ],
      "source": [
        "@function_tool\n",
        "def random_number(max: int) -> int:\n",
        "    \"\"\"\n",
        "    Generate a random number up to the provided maximum.\n",
        "    \"\"\"\n",
        "    return random.randint(0, max)\n",
        "\n",
        "\n",
        "@function_tool\n",
        "def multiply_by_two(x: int) -> int:\n",
        "    \"\"\"Simple multiplication by two.\"\"\"\n",
        "    return x * 2\n",
        "\n",
        "\n",
        "class FinalResult(BaseModel):\n",
        "    number: int\n",
        "\n",
        "\n",
        "multiply_agent = Agent(\n",
        "    name=\"Multiply Agent\",\n",
        "    instructions=\"Multiply the number by 2 and then return the final result.\",\n",
        "    tools=[multiply_by_two],\n",
        "    hooks=CustomAgentHooks(display_name=\"Multiply Agent\"),\n",
        "    model=model\n",
        ")\n",
        "\n",
        "start_agent = Agent(\n",
        "    name=\"Start Agent\",\n",
        "    instructions=\"Generate a random number. If it's even, stop. If it's odd, hand off to the multiply agent.\",\n",
        "    tools=[random_number],\n",
        "    handoffs=[multiply_agent],\n",
        "    hooks=CustomAgentHooks(display_name=\"Start Agent\"),\n",
        "    model=model\n",
        "\n",
        ")\n",
        "\n",
        "\n",
        "async def main() -> None:\n",
        "    user_input = input(\"Enter a max number: \")\n",
        "    await Runner.run(\n",
        "        start_agent,\n",
        "        input=f\"Generate a random number between 0 and {user_input}.\",\n",
        "    )\n",
        "\n",
        "    print(\"Done!\")\n",
        "\n",
        "\n",
        "asyncio.run(main())"
      ]
    }
  ],
  "metadata": {
    "colab": {
      "provenance": []
    },
    "kernelspec": {
      "display_name": "Python 3",
      "name": "python3"
    },
    "language_info": {
      "name": "python"
    }
  },
  "nbformat": 4,
  "nbformat_minor": 0
}
